# -*- coding: utf-8 -*-
# @Author: Jerry
# @Date:   2022-03-09 17:12:39
# @Last Modified by:   Jerry
# @Last Modified time: 2022-03-09 17:52:05

# **********
# 使用自定义内核对图像进行卷积。
# 该功能将任意线性滤波器应用于图像。
# 支持就地操作。
# 当光圈部分位于图像外部时，该功能会根据指定的边框模式插入异常像素值。
# https://www.cnblogs.com/lfri/p/10599420.html
#

# **********
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
import os
rootpath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
datapath = os.path.join(rootpath,'data')
imgpath = lambda name: os.path.join(datapath,name)


# **********
'''语法
函数原型：
dst=cv.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]])
src         原图像
dst         目标图像，与原图像尺寸和通过数相同
ddepth      目标图像的所需深度,当ddepth=-1时，表示输出图像与原图像有相同的深度。
kernel      卷积核（或相当于相关核），单通道浮点矩阵;如果要将不同的内核应用于不同的通道，请使用拆分将图像拆分为单独的颜色平面，然后单独处理它们。
anchor      内核的锚点，指示内核中过滤点的相对位置;锚应位于内核中;默认值（-1，-1）表示锚位于内核中心。
detal       在将它们存储在dst中之前，将可选值添加到已过滤的像素中。类似于偏置。
borderType  像素外推法，参见BorderTypes'''


# 1. 模糊(blur) 内核
# 模糊内核消除了相邻像素值之间的差异
kernel_blur = np.array((
        [0.0625, 0.125, 0.0625],
        [0.125 , 0.25 , 0.125 ],
        [0.0625, 0.125, 0.0625]), dtype="float32")


# 2、索贝尔（sobel）
# sobel内核用于仅显示特定方向上相邻像素值的差异，
# 分为left sobel、right sobel（检测梯度的水平变化）、
# top sobel、buttom sobel（检测梯度的垂直变化）。
# 例如，buttom sobel
kernel_sobel_bottom = np.array((
        [-1, -2, -1],
        [ 0,  0,  0],
        [ 1,  2,  1]), dtype="float32")


# 3、浮雕（emboss）
# 通过强调像素的差在给定方向的Givens深度的错觉。在这种情况下，沿着从左上到右下的直线的方向。
kernel_emboss = np.array((
        [-2, -1,  0],
        [-1,  1,  1],
        [ 0,  1,  2]), dtype="float32")


# 4、大纲（outline）
# 一个轮廓内核（也称为“边缘”的内核）用于突出显示的像素值大的差异。
# 具有接近相同强度的相邻像素旁边的像素在新图像中将显示为黑色，而与强烈不同的相邻像素相邻的像素将显示为白色。
kernel_outline = np.array((
        [-1, -1,  -1],
        [-1,  8,  -1],
        [-1, -1,  -1]), dtype="float32")


# 5、锐化（sharpen）
# 该锐化内核强调在相邻的像素值的差异。这使图像看起来更生动。
kernel_sharpen = np.array((
        [ 0, -1,   0],
        [-1,  5,  -1],
        [ 0, -1,   0]), dtype="float32")


# 6、拉普拉斯算子（laplacian operator）
# 拉普拉斯算子可以用于边缘检测，对于检测图像中的模糊也非常有用。
kernel_laplacian = np.array((
        [ 0,  1,   0],
        [ 1, -4,   1],
        [ 0,  1,   0]), dtype="float32")


# 7、分身（identity）
# 这个非常简单，就是原图（不考虑边界时），How boring!
kernel_identity = np.array((
        [ 0,  0,   0],
        [ 0,  1,   0],
        [ 0,  0,   0]), dtype="float32")


if __name__ == '__main__':
    kernels = [kernel_blur,kernel_sobel_bottom,kernel_emboss,
               kernel_outline,kernel_sharpen,kernel_laplacian,
               kernel_identity]
    src = cv.imread(imgpath('ma.png'))
    if src is None:
        print "read file none"
        exit(1)
    for i in range(len(kernels)):
        dst = cv.filter2D(src,-1,kernels[i])
        htich = np.hstack((src,dst))
        cv.imshow(str(i),htich)
    cv.waitKey(0)





